#include "Name.h"
#include "Containers/Map.h"

class CNamePool
{
public:
    CNamePool(const CString& InNameBase)
    {
        NameBase=InNameBase;
    }

    CString GetNameBase()
    {
        return NameBase;
    }

    CName NewName()
    {
        return CName(this,++MaxIndex);
    }
private:
    uint32_t MaxIndex=0;
    CString NameBase;
};

class CNamePoolManager
{
public:    
    static CNamePool* FindOrAddNamePool(const CString& InNameBase)
    {
        //auto FoundPos=AllNamePool.find(InNameBase);

        if(AllNamePool.Contains(InNameBase))
        {
            return AllNamePool[InNameBase];
        }

        // if(FoundPos!=AllNamePool.end())
        // {
        //     return FoundPos->second;
        // }

        auto NewPool=new CNamePool(InNameBase);
        AllNamePool.Add(InNameBase,NewPool);// .insert(make_pair(InNameBase,NewPool));
        return NewPool;

    }

private:
    static TMap<CString /*name base CString*/,CNamePool*> AllNamePool;

};
TMap<CString /*name base CString*/,CNamePool*> CNamePoolManager::AllNamePool={};

CString CName::ToString() const
{
    return NamePool->GetNameBase() + (Index != 0 ? U"_" + CString((uint64_t)Index) : U"");
}

CName::CName(const CString& NameInString)
{
    auto Pos=NameInString.Find(U'_',true);

    CString BaseName;
    //uint64_t NameIndex=0;

    if(Pos!=-1)
    {
        BaseName=NameInString.SubString(0,Pos);
        Index=NameInString.SubString(Pos+1).ToInt64(); 
    }else
    {
        BaseName=NameInString;
    }

    NamePool=CNamePoolManager::FindOrAddNamePool(BaseName);
}

CName CName::MakeUniqueName(const CString& InBaseName)
{
    CNamePool* Pool= CNamePoolManager::FindOrAddNamePool(InBaseName);

    return Pool->NewName();
}

CName CName::MakeUniqueName(const CName& InBaseName)
{
    CNamePool* Pool= InBaseName.NamePool;

    return Pool->NewName();
}